﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKGeometryFuncs;
using YJKRevitDimensionText.DimCreator;
using YJKRevitDimensionText.OneKeyPlanDim.DimesionDataEx;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.OutWallThreeDim
{
	public class OutWallThreeDimManagerEx
	{
		public OutWallThreeDimManagerEx(UIApplication uiApp, Autodesk.Revit.DB.Document doc, Autodesk.Revit.DB.View view)
		{
			this.m_uiApp = uiApp;
			this.m_doc = doc;
			this.m_view = view;
		}

		public List<Dimension> GetAllThreeDim(BaseDataOper baseData, ref List<ElementId> lstDimId)
		{
			List<Dimension> list = new List<Dimension>();
			try
			{
				foreach (SizeDimData sizeDimData in this.GetAllThreeDimData(baseData, ref lstDimId))
				{
					Dimension dimension = sizeDimData.CreateDim(false);
					if (dimension != null)
					{
						list.Add(dimension);
					}
				}
				foreach (Dimension inputDim in list)
				{
					DimAvoidManager.ClearCache();
					DimAvoidManager.TryAutoAvoidForHorizontal(this.m_doc, inputDim);
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		public List<SizeDimData> GetAllThreeDimData(BaseDataOper baseData, ref List<ElementId> lstDimId)
		{
			List<SizeDimData> list = new List<SizeDimData>();
			try
			{
				foreach (KeyValuePair<GridGroupDataEx, List<WallDataMerge>> pairValue in WallOperattionUtil.GetOutWallDataByGrid(this.m_uiApp, baseData))
				{
					List<XYZ> list2 = new List<XYZ>();
					List<XYZ> collection = new List<XYZ>();
					List<XYZ> list3 = new List<XYZ>();
					XYZ vecGrid = pairValue.Key.VecGridNum.Normalize();
					if (this.GetThreeDimRefPoint(pairValue, ref list2, ref collection, ref list3, ref lstDimId))
					{
						Line line = WallOperattionUtil.GetOneGridGroupMaxWallCurve(pairValue.Key, pairValue.Value) as Line;
						if (!(null == line))
						{
							List<SizeDimData> pointDimData = this.GetPointDimData(list2, vecGrid, line, 11.15485564304462);
							if (pointDimData.Count > 0)
							{
								list.AddRange(pointDimData);
							}
							List<XYZ> list4 = new List<XYZ>();
							list4.AddRange(list2);
							list4.AddRange(collection);
							List<XYZ> lstProfilePt = ParallelLinesUtils.RemoveDuplicatedPoint(list4);
							List<SizeDimData> pointDimData2 = this.GetPointDimData(lstProfilePt, vecGrid, line, 8.530183727034121);
							if (pointDimData2.Count > 0)
							{
								list.AddRange(pointDimData2);
							}
							if (list3.Count > 0)
							{
								List<XYZ> list5 = new List<XYZ>();
								list5.AddRange(list2);
								list5.AddRange(collection);
								list5.AddRange(list3);
								List<XYZ> lstProfilePt2 = ParallelLinesUtils.RemoveDuplicatedPoint(list5);
								List<SizeDimData> pointDimData3 = this.GetPointDimData(lstProfilePt2, vecGrid, line, 5.9055118110236222);
								if (pointDimData3.Count > 0)
								{
									list.AddRange(pointDimData3);
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		private List<SizeDimData> GetPointDimData(List<XYZ> lstProfilePt, XYZ vecGrid, Line lineDim, double dDimTrans)
		{
			List<SizeDimData> list = new List<SizeDimData>();
			if (lstProfilePt.Count > 1)
			{
				ReferenceArray referenceArray = new ReferenceArray();
				List<DetailCurve> list2 = new List<DetailCurve>();
				using (Transaction transaction = new Transaction(this.m_doc, "newDetailCv"))
				{
					try
					{
						transaction.Start();
						foreach (XYZ xyz in lstProfilePt)
						{
							XYZ xyz2 = xyz + vecGrid.Multiply(0.0032808398950131233);
							Line line = Line.CreateBound(xyz, xyz2);
							DetailCurve detailCurve = this.m_doc.Create.NewDetailCurve(this.m_view, line);
							if (detailCurve != null)
							{
								list2.Add(detailCurve);
							}
						}
						transaction.Commit();
					}
					catch (Exception)
					{
						transaction.RollBack();
					}
				}
				if (list2.Count > 0)
				{
					foreach (DetailCurve detailCurve2 in list2)
					{
						referenceArray.Append(detailCurve2.GeometryCurve.Reference);
					}
					Line line2 = lineDim.CreateTransformed(Transform.CreateTranslation(vecGrid.Multiply(dDimTrans))) as Line;
					SizeDimData item = new SizeDimData(this.m_doc, line2, referenceArray);
					list.Add(item);
				}
			}
			return list;
		}

		private bool GetThreeDimRefPoint(KeyValuePair<GridGroupDataEx, List<WallDataMerge>> pairValue, ref List<XYZ> lstProfilePt, ref List<XYZ> lstGridPt, ref List<XYZ> lstWinDoorPt, ref List<ElementId> lstDimId)
		{
			try
			{
				List<XYZ> list = new List<XYZ>();
				Curve oneGridGroupMaxWallCurve = WallOperattionUtil.GetOneGridGroupMaxWallCurve(pairValue.Key, pairValue.Value);
				if (!(null != oneGridGroupMaxWallCurve))
				{
					return false;
				}
				oneGridGroupMaxWallCurve.MakeUnbound();
				foreach (Line line in pairValue.Key.LstLine)
				{
					XYZ xyzpoint = oneGridGroupMaxWallCurve.Project(line.GetEndPoint(0)).XYZPoint;
					if (xyzpoint != null)
					{
						list.Add(xyzpoint);
					}
				}
				List<XYZ> list2 = new List<XYZ>();
				this.GetGridDirValidWinDoorPoint(pairValue, oneGridGroupMaxWallCurve, list2, ref lstDimId);
				List<XYZ> list3 = new List<XYZ>();
				this.GetGridDirValidWallPoint(pairValue, oneGridGroupMaxWallCurve, list3);
				List<XYZ> list4 = new List<XYZ>();
				list4.AddRange(list);
				list4.AddRange(list3);
				list4.AddRange(list2);
				if (list4.Count > 1)
				{
					List<XYZ> source = ParallelLinesUtils.SortPointsWithVector(ParallelLinesUtils.RemoveDuplicatedPoint(list4), (oneGridGroupMaxWallCurve as Line).Direction.Normalize());
					lstProfilePt.Add(source.First<XYZ>());
					lstProfilePt.Add(source.Last<XYZ>());
				}
				if (list.Count > 0)
				{
					lstGridPt.AddRange(list);
				}
				if (list2.Count > 0)
				{
					lstWinDoorPt.AddRange(list2);
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private void GetGridDirValidWallPoint(KeyValuePair<GridGroupDataEx, List<WallDataMerge>> pairValue, Curve CvProj, List<XYZ> lstTempWallPoint)
		{
			foreach (WallDataMerge wallDataMerge in pairValue.Value)
			{
				Line line = wallDataMerge.MergeProfileLine as Line;
				if (!(null == line))
				{
					if (Geometry.IsParallel(line.Direction.Normalize(), pairValue.Key.VecGridNum.Normalize()))
					{
						XYZ endPoint = wallDataMerge.MergeProfileLine.GetEndPoint(0);
						XYZ vecGrid = pairValue.Key.VecGridNum.Normalize();
						List<WallDataMerge> pointVectWallMerge = WallOperattionUtil.GetPointVectWallMerge(pairValue.Value, endPoint, vecGrid);
						bool flag = WallOperattionUtil.IsWinDoorValid(this.m_uiApp, pointVectWallMerge, wallDataMerge.MergeProfileLine, vecGrid);
						bool flag2 = WallOperattionUtil.IsWallIn6MRange(pairValue.Key, wallDataMerge.MergeProfileLine, true);
						if (flag && flag2)
						{
							XYZ xyzpoint = CvProj.Project(endPoint).XYZPoint;
							if (xyzpoint != null)
							{
								lstTempWallPoint.Add(xyzpoint);
							}
						}
					}
					else if (WallOperattionUtil.IsWallIn6MRange(pairValue.Key, wallDataMerge.MergeProfileLine, false))
					{
						XYZ xyzpoint2 = CvProj.Project(wallDataMerge.MergeProfileLine.GetEndPoint(0)).XYZPoint;
						XYZ xyzpoint3 = CvProj.Project(wallDataMerge.MergeProfileLine.GetEndPoint(1)).XYZPoint;
						if (xyzpoint2 != null && xyzpoint3 != null)
						{
							lstTempWallPoint.Add(xyzpoint2);
							lstTempWallPoint.Add(xyzpoint3);
						}
					}
				}
			}
		}

		private void GetGridDirValidWinDoorPoint(KeyValuePair<GridGroupDataEx, List<WallDataMerge>> pairValue, Curve CvProj, List<XYZ> lstTempWinDoorPt, ref List<ElementId> lstDimId)
		{
			XYZ vecVertGrid = Transform.CreateRotation(XYZ.BasisZ, Math.PI*.5).OfVector(pairValue.Key.VecGridNum.Normalize());
			foreach (WallDataMerge wallDataMerge in WallOperattionUtil.GetVectorWallMerge(pairValue.Value, vecVertGrid))
			{
				foreach (WallDataEx wallDataEx in wallDataMerge.LstWallData)
				{
					foreach (DoorWinDataEx doorWinDataEx in wallDataEx.WallWindows)
					{
						Line doorWinLine = doorWinDataEx.doorWinLine;
						Line line = doorWinDataEx.CheckDoorWinLind();
						if (null != doorWinLine && null != line)
						{
							doorWinLine.GetEndPoint(0);
							XYZ endPoint = wallDataMerge.MergeProfileLine.GetEndPoint(0);
							XYZ vecGrid = pairValue.Key.VecGridNum.Normalize();
							List<WallDataMerge> pointVectWallMerge = WallOperattionUtil.GetPointVectWallMerge(pairValue.Value, endPoint, vecGrid);
							bool flag = WallOperattionUtil.IsWinDoorValid(this.m_uiApp, pointVectWallMerge, line, vecGrid);
							bool flag2 = WallOperattionUtil.IsWallIn6MRange(pairValue.Key, doorWinLine, true);
							if (flag && flag2)
							{
								XYZ xyzpoint = CvProj.Project(doorWinLine.GetEndPoint(0)).XYZPoint;
								XYZ xyzpoint2 = CvProj.Project(doorWinLine.GetEndPoint(1)).XYZPoint;
								if (xyzpoint != null && xyzpoint2 != null)
								{
									lstTempWinDoorPt.Add(xyzpoint);
									lstTempWinDoorPt.Add(xyzpoint2);
									if (null != doorWinDataEx.DWId)
									{
										lstDimId.Add(doorWinDataEx.DWId);
									}
								}
							}
						}
					}
				}
			}
		}

		private const double m_d1800MM = 5.9055118110236222;

		private const double m_d800MM = 2.6246719160104988;

		private const double m_d1MM = 0.0032808398950131233;

		private Document m_doc;

		private UIApplication m_uiApp;

		private Autodesk.Revit.DB.View m_view;
	}
}
